import json
from decimal import Decimal

from django import http
from django.core.paginator import Paginator
from django.db import transaction
from django.shortcuts import render

# Create your views here.
from django.utils import timezone
from django.views import View
import logging
from goods.models import SKU
from meiduo_mall.utils.response_code import RETCODE
from meiduo_mall.utils.view import LoginRequiredMixin
from orders.models import OrderInfo
from users.models import Address
from django_redis import get_redis_connection
logger = logging.getLogger('django')


class OrdersSettlementView(LoginRequiredMixin, View):
    def get(self, request):
        user = request.user
        try:
            addresses = Address.objects.get(id=user.id, is_deleted=False)
        except Address.DoesNotExist:
            addresses = None

        redis_conn = get_redis_connection('carts')
        item_dict = redis_conn.hgetall('cart_%s' % user.id)
        cart_selected = redis_conn.smembers('cart_%s' % user.id)
        dicts = {}
        for sku_id in cart_selected:
            dicts[int(sku_id)] = int(item_dict[sku_id])

        all_count = 0
        all_price = Decimal(0.00)

        skus = SKU.objects.filter(id__in=dicts.keys())
        for sku in skus:
            sku.count = dicts[sku.id]
            sku.amount = sku.count * sku.price
            all_count += sku.count
            all_price += sku.amount

        freight = Decimal('10.00')

        context = {
            'addresses': addresses,
            'skus': skus,
            'total_count': all_count,
            'total_amount': all_price,
            'freight': freight,
            'payment_amount': all_price + freight
        }

        return render(request, 'place_order.html', context)


class OrdersCommitView(LoginRequiredMixin, View):
    def post(self, request):
        json_dict = json.loads(request.body.decode())
        address_id = json_dict.get('address_id')
        pay_method = json_dict.get('pay_method')

        if not all([address_id, pay_method]):
            return http.HttpResponseForbidden('缺少参数')

        try:
            address = Address.objects.get(id=address_id)
        except Exception:
            return http.HttpResponseForbidden('地址不存在')

        if pay_method not in [OrderInfo.PAY_METHODS_ENUM["CASH"],
                              OrderInfo.PAY_METHODS_ENUM["ALIPAY"]]:
            return http.HttpResponseForbidden('支付方式错误')

        user = request.user

        order_id = timezone.localtime().strftime('%Y%m%d%H%M%S') + ('%09d' % user.id)

        with transaction.atomic():
            save_id = transaction.savepoint()
            try:

                order = OrderInfo.objects.create(
                    order_id=order_id,
                    user=user,
                    address=address,
                    total_count=0,
                    total_amount=Decimal('0'),
                    freight=Decimal('10.00'),
                    pay_method=pay_method,
                    status=OrderInfo.ORDER_STATUS_ENUM['UNPAID'] if pay_method == OrderInfo.PAY_METHODS_ENUM["ALIPAY"] else OrderInfo.ORDER_STATUS_ENUM['UNSEND']
                )
                redis_conn = get_redis_connection('carts')
                item_dict = redis_conn.hgetall('cart_%s' % user.id)
                cart_selected = redis_conn.smembers('cart_%s' % user.id)
                carts = {}
                for sku_id in cart_selected:
                    carts[int(sku_id)] = int(item_dict[sku_id])

                skus_id = SKU.objects.filter(id__in=carts.keys())
                for sku_id in skus_id:
                    while True:
                        sku = SKU.objects.get(id=sku_id)

                        origin_stock = sku.stock
                        origin_sales = sku.sales

                        sku_count = carts[sku.id]
                        if sku_count > origin_stock:
                            transaction.savepoint_rollback(save_id)
                            return http.JsonResponse({'code': RETCODE.STOCKERR,
                                                      'errmsg': '库存不足'})
                        # sku.stock -= sku_count
                        # sku.sales += sku_count
                        # sku.save()
                        new_stock = origin_stock - sku_count
                        new_sales = origin_sales + sku_count
                        result = SKU.objects.filter(
                            id=sku_id,
                            stock=origin_stock
                        ).update(stock=new_stock, sales=new_sales)

                        if result == 0:
                            continue

                        sku.goods.sales += sku_count
                        sku.goods.save()
                        OrderInfo.objects.create(
                            order=order,
                            sku=sku,
                            count=sku_count,
                            price=sku.price,
                        )
                        order.total_count += sku_count
                        order.total_amount += sku.price * sku_count
                        break

                order.total_amount += order.freight
                order.save()
            except Exception as e:
                logger.error(e)
                transaction.savepoint_rollback(save_id)
                return http.JsonResponse({'code': RETCODE.DBERR,
                                          'errmsg': '下单失败'})
            transaction.savepoint_commit(save_id)
        pl = redis_conn.pipeline()
        pl.hdel('cart_%s' % user.id, *cart_selected)
        pl.srem('cart_%s' % user.id, *cart_selected)
        pl.execute()

        return http.JsonResponse({'code': RETCODE.OK,
                                  'errmsg': 'ok',
                                  'order_id': order.order_id})


class OrdersSuccessView(LoginRequiredMixin, View):
    def get(self, request):
        order_id = request.GET.get('order_id')
        payment_amount = request.GET.get('payment_amount')
        pay_method = request.GET.get('pay_method')

        context = {
            'order_id': order_id,
            'payment_amount': payment_amount,
            'pay_method': pay_method
        }

        return render(request, 'order_success.html', context)


class OrdersInfoView(View):
    def get(self, request, page_num):
        user = request.user
        orders = user.orderinfo_set.all().order_by('-create_time')

        for order in orders:
            order.status_name = OrderInfo.ORDER_STATUS_CHOICES[order.status - 1][1]
            order.pay_method_name = OrderInfo.PAY_METHOD_CHOICES[order.pay_method - 1][1]
            order_list = []
            order_goods = order.skus.all()
            for order_good in order_goods:
                sku = order_good.sku
                sku.count = order_good.count
                sku.amount = sku.price * sku.count
                order_list.append(sku)

        page_num = int(page_num)
        try:
            paginator = Paginator(orders, 2)
            paginator_num = paginator.page(page_num)
            paginator_nums = paginator.num_pages()
        except Exception as e:
            return http.HttpResponseForbidden('商品不存在')

        context = {
            "page_orders": paginator_num,
            'total_page': paginator_nums,
            'page_num': page_num,
        }

        return render(request, 'user_center_order.html', context)